using System;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using System.Security.Permissions;
using Lizk.Utilities;
using XNAHUDEngine;
using SharpMedia.Input;
using SharpMedia.XNA;
using Lizk.SimpleHUD;
using SharpMedia.Pages;
using XNAHUDEngine.Properties;

namespace SharpMedia
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            if (SystemTools.ProcessAlreadyRunning())
                return;

            Application.EnableVisualStyles();

            SharpMedia.RootDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            if (!Directory.Exists(SharpMedia.RootDirectory))
                Directory.CreateDirectory(SharpMedia.RootDirectory);

            if (args.Length != 0)
            {
                //Application.Run(new SettingsForm());
                return;
            }

            FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
            perm.Demand();
            
            Thread.CurrentThread.Name = "Form Thread";


            SharpMedia.LoadSettings(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "felizk"), "SharpMedia"));

             // Form and Renderer are so tightly bound it is almost silly for them to be separate classes but the form would become ENORMOUS if not
            XNAForm Form = new XNAHUDEngine.XNAForm() 
            {
                //Icon = Resources.screen,
                Text = "SharpMedia XNA",
                Windowed = SharpMedia.Settings.WindowedMode,
                WindowSize = SharpMedia.Settings.WindowSize,
                Icon = Resources.screen
            };
            Form.InitializeDevice();
            
            Form.WindowsMessages += new XNAHUDEngine.XNAForm.WndProcHandler(delegate(ref System.Windows.Forms.Message m, ref bool call) { OverlayPage2.diskMonitor.PreFilterMessage(ref m); });

            SharpMedia.renderer = new XNARenderer(Form)
            {
                ImageRoot = Path.Combine(SharpMedia.RootDirectory, "images"),
                FontRootDir = Path.Combine(SharpMedia.RootDirectory, @"fonts"),
                GarbageCollectionInterval = new TimeSpan(0, 4, 30)
            };
            SharpMedia.Engine = Form;
            
            
            Form.Renderer = (XNARenderer)SharpMedia.renderer;

            Form.DoUpdate += new EventHandler(Form_DoUpdate);
            Form.Render += new EventHandler(Form_Render);
            Form.FormClosing += new FormClosingEventHandler(Form_FormClosing);
            Form.Shown += new EventHandler(Form_Shown);
            Form.MouseDown += new MouseEventHandler(Form_MouseDown);
            Form.MouseUp += new MouseEventHandler(Form_MouseUp);

            // Input Class
            FormInputController formInput = new FormInputController(Path.Combine(SharpMedia.DataDirectory, "commands.xml"), Form);
            formInput.FireCommand += new EventHandler<CommandEventArgs>(SharpMedia.HandleInput);

            Application.Run(Form);

        }

        static void Form_Shown(object sender, EventArgs e)
        {
            Util.RunAsync(SharpMedia.Init, Thread.CurrentThread);
        }

        static void Form_FormClosing(object sender, FormClosingEventArgs e)
        {
            SharpMedia.Closing();
        }

        static void Form_Render(object sender, EventArgs e)
        {
            SharpMedia.Render();
        }

        static void Form_DoUpdate(object sender, EventArgs e)
        {
            SharpMedia.Update();
        }

        static void Form_MouseUp(object sender, MouseEventArgs e)
        {
            HUDControl.MouseButtons button = HUDControl.MouseButtons.None;
            switch (e.Button)
            {
                case MouseButtons.Left:
                    button = HUDControl.MouseButtons.Left;
                    break;
                case MouseButtons.Middle:
                    button = HUDControl.MouseButtons.Middle;
                    break;
                case MouseButtons.None:
                    button = HUDControl.MouseButtons.None;
                    break;
                case MouseButtons.Right:
                    button = HUDControl.MouseButtons.Right;
                    break;
                default:
                    break;
            }
            SharpMedia.MouseUp(new Lizk.SimpleHUD.PointS(e.X, e.Y), button);
        }

        static void Form_MouseDown(object sender, MouseEventArgs e)
        {
            HUDControl.MouseButtons button = HUDControl.MouseButtons.None;
            switch (e.Button)
            {
                case MouseButtons.Left:
                    button = HUDControl.MouseButtons.Left;
                    break;
                case MouseButtons.Middle:
                    button = HUDControl.MouseButtons.Middle;
                    break;
                case MouseButtons.None:
                    button = HUDControl.MouseButtons.None;
                    break;
                case MouseButtons.Right:
                    button = HUDControl.MouseButtons.Right;
                    break;
                default:
                    break;
            }
            SharpMedia.MouseDown(new PointS(e.X, e.Y), button);
        }


    }
}
